using System;
using System.Collections.Generic;
using System.Linq;

namespace MT5Trade.Models
{
    /// <summary>
    /// ATR计算和动态止损调整核心类
    /// 基于平均真实波幅和历史波动率实现科学的动态止损系统
    /// </summary>
    public class ATRCalculator
    {
        #region 常量定义

        // ATR计算参数
        public const int DEFAULT_ATR_PERIOD = 14;      // 默认ATR周期
        public const int MIN_ATR_PERIOD = 5;           // 最小ATR周期
        public const int MAX_ATR_PERIOD = 50;          // 最大ATR周期

        // 波动率调整因子
        public const double LOW_VOLATILITY_MULTIPLIER = 1.5;     // 低波动率环境倍数
        public const double MEDIUM_VOLATILITY_MULTIPLIER = 2.0;  // 中等波动率环境倍数
        public const double HIGH_VOLATILITY_MULTIPLIER = 2.5;    // 高波动率环境倍数

        // 趋势识别参数
        public const double TREND_THRESHOLD = 0.6;     // 趋势判断阈值
        public const int TREND_LOOKBACK_PERIOD = 20;   // 趋势识别回顾期

        // 止损调整参数
        public const double MIN_STOP_DISTANCE_RATIO = 0.005;  // 最小止损距离比例0.5%
        public const double MAX_STOP_DISTANCE_RATIO = 0.10;   // 最大止损距离比例10%
        public const double TRAILING_STEP_RATIO = 0.3;        // 跟踪止损步长比例

        // EWMA平滑参数
        public const double EWMA_LAMBDA = 0.94;        // EWMA衰减因子

        #endregion

        #region 私有字段

        private readonly List<PriceData> _historicalData;
        private readonly List<double> _atrValues;
        private readonly List<double> _volatilityEstimates;
        private readonly int _atrPeriod;
        private DateTime _lastUpdateTime;

        // 趋势相关状态
        private double _currentTrend;
        private TrendDirection _trendDirection;
        private double _trendStrength;

        // 止损追踪状态
        private double _highestProfit;
        private double _lowestProfit;
        private double _currentStopLevel;

        #endregion

        #region 枚举定义

        /// <summary>
        /// 趋势方向枚举
        /// </summary>
        public enum TrendDirection
        {
            Unknown = 0,
            Uptrend = 1,
            Downtrend = -1,
            Sideways = 2
        }

        /// <summary>
        /// 波动率环境枚举
        /// </summary>
        public enum VolatilityEnvironment
        {
            Low,
            Medium, 
            High,
            Extreme
        }

        #endregion

        #region 价格数据结构

        /// <summary>
        /// 价格数据结构
        /// </summary>
        public class PriceData
        {
            public DateTime Time { get; set; }
            public double Open { get; set; }
            public double High { get; set; }
            public double Low { get; set; }
            public double Close { get; set; }
            public double Volume { get; set; }

            public PriceData(DateTime time, double open, double high, double low, double close, double volume = 0)
            {
                Time = time;
                Open = open;
                High = high;
                Low = low;
                Close = close;
                Volume = volume;
            }

            /// <summary>
            /// 计算真实波幅
            /// TR = MAX(H-L, ABS(H-Prev_C), ABS(L-Prev_C))
            /// </summary>
            public double CalculateTrueRange(double previousClose)
            {
                double hl = High - Low;
                double hc = Math.Abs(High - previousClose);
                double lc = Math.Abs(Low - previousClose);

                return Math.Max(hl, Math.Max(hc, lc));
            }
        }

        #endregion

        #region 构造函数

        /// <summary>
        /// 初始化ATR计算器
        /// </summary>
        /// <param name="atrPeriod">ATR计算周期</param>
        public ATRCalculator(int atrPeriod = DEFAULT_ATR_PERIOD)
        {
            if (atrPeriod < MIN_ATR_PERIOD || atrPeriod > MAX_ATR_PERIOD)
            {
                throw new ArgumentException($"ATR周期必须在{MIN_ATR_PERIOD}到{MAX_ATR_PERIOD}之间");
            }

            _atrPeriod = atrPeriod;
            _historicalData = new List<PriceData>();
            _atrValues = new List<double>();
            _volatilityEstimates = new List<double>();
            _lastUpdateTime = DateTime.MinValue;

            // 初始化趋势相关状态
            _currentTrend = 0.0;
            _trendDirection = TrendDirection.Unknown;
            _trendStrength = 0.0;

            // 初始化止损追踪状态
            _highestProfit = 0.0;
            _lowestProfit = 0.0;
            _currentStopLevel = 0.0;
        }

        #endregion

        #region 核心ATR计算方法

        /// <summary>
        /// 添加价格数据并更新ATR
        /// </summary>
        /// <param name="priceData">价格数据</param>
        public void AddPriceData(PriceData priceData)
        {
            if (priceData == null)
            {
                throw new ArgumentNullException(nameof(priceData));
            }

            _historicalData.Add(priceData);

            // 限制历史数据长度，保持最新数据
            if (_historicalData.Count > _atrPeriod * 3)
            {
                _historicalData.RemoveRange(0, _historicalData.Count - _atrPeriod * 3);
            }

            // 更新ATR和波动率
            UpdateATR();
            UpdateVolatilityEstimates();
            UpdateTrendAnalysis();

            _lastUpdateTime = DateTime.Now;
        }

        /// <summary>
        /// 计算简化的ATR（仅使用收盘价）
        /// </summary>
        /// <param name="prices">价格序列</param>
        /// <param name="period">ATR周期</param>
        /// <returns>ATR值</returns>
        public double CalculateATR(IEnumerable<double> prices, int? period = null)
        {
            var priceList = prices.ToList();
            int atrPeriod = period ?? _atrPeriod;

            if (priceList.Count < atrPeriod + 1)
            {
                return 0.0;
            }

            var trueRanges = new List<double>();

            // 计算真实波幅（简化版）
            for (int i = 1; i < priceList.Count; i++)
            {
                double tr = Math.Abs(priceList[i] - priceList[i - 1]);
                trueRanges.Add(tr);
            }

            // 计算ATR（移动平均）
            if (trueRanges.Count < atrPeriod)
            {
                return trueRanges.Average();
            }

            return trueRanges.Skip(trueRanges.Count - atrPeriod).Average();
        }

        /// <summary>
        /// 计算完整的ATR（使用OHLC数据）
        /// </summary>
        /// <returns>当前ATR值</returns>
        public double CalculateFullATR()
        {
            if (_historicalData.Count < _atrPeriod + 1)
            {
                return 0.0;
            }

            var trueRanges = new List<double>();

            // 计算每个周期的真实波幅
            for (int i = 1; i < _historicalData.Count; i++)
            {
                double tr = _historicalData[i].CalculateTrueRange(_historicalData[i - 1].Close);
                trueRanges.Add(tr);
            }

            if (trueRanges.Count < _atrPeriod)
            {
                return trueRanges.Average();
            }

            // 使用指数移动平均计算ATR
            return CalculateEMA(trueRanges.Skip(trueRanges.Count - _atrPeriod), _atrPeriod);
        }

        /// <summary>
        /// 获取当前ATR值
        /// </summary>
        /// <returns>最新的ATR值</returns>
        public double GetCurrentATR()
        {
            return _atrValues.LastOrDefault();
        }

        #endregion

        #region 波动率估计方法

        /// <summary>
        /// 计算历史波动率
        /// </summary>
        /// <param name="period">计算周期</param>
        /// <returns>历史波动率（年化）</returns>
        public double CalculateHistoricalVolatility(int? period = null)
        {
            int volPeriod = period ?? _atrPeriod;

            if (_historicalData.Count < volPeriod + 1)
            {
                return 0.0;
            }

            var returns = new List<double>();

            // 计算收益率
            for (int i = 1; i < Math.Min(_historicalData.Count, volPeriod + 1); i++)
            {
                double return_rate = Math.Log(_historicalData[_historicalData.Count - i].Close / 
                                            _historicalData[_historicalData.Count - i - 1].Close);
                returns.Add(return_rate);
            }

            // 计算标准差
            double mean = returns.Average();
            double variance = returns.Sum(r => Math.Pow(r - mean, 2)) / (returns.Count - 1);
            double dailyVol = Math.Sqrt(variance);

            // 年化波动率（假设每年250个交易日）
            return dailyVol * Math.Sqrt(250);
        }

        /// <summary>
        /// 计算EWMA波动率
        /// </summary>
        /// <param name="lambda">衰减因子</param>
        /// <returns>EWMA波动率</returns>
        public double CalculateEWMAVolatility(double lambda = EWMA_LAMBDA)
        {
            if (_historicalData.Count < 2)
            {
                return 0.0;
            }

            var returns = new List<double>();

            // 计算收益率
            for (int i = 1; i < _historicalData.Count; i++)
            {
                double return_rate = Math.Log(_historicalData[i].Close / _historicalData[i - 1].Close);
                returns.Add(return_rate);
            }

            if (returns.Count < 2)
            {
                return 0.0;
            }

            // EWMA方差计算
            double ewmaVariance = Math.Pow(returns[0], 2);

            for (int i = 1; i < returns.Count; i++)
            {
                ewmaVariance = lambda * ewmaVariance + (1 - lambda) * Math.Pow(returns[i], 2);
            }

            // 年化波动率
            return Math.Sqrt(ewmaVariance * 250);
        }

        /// <summary>
        /// 获取GARCH波动率（需要GarchModel支持）
        /// </summary>
        /// <param name="garchModel">GARCH模型实例</param>
        /// <returns>GARCH预测波动率</returns>
        public double GetGARCHVolatility(GarchModel garchModel)
        {
            if (garchModel == null)
            {
                throw new ArgumentNullException(nameof(garchModel));
            }

            if (_historicalData.Count < 2)
            {
                return 0.0;
            }

            var returns = new List<double>();

            // 计算收益率
            for (int i = 1; i < _historicalData.Count; i++)
            {
                double return_rate = Math.Log(_historicalData[i].Close / _historicalData[i - 1].Close);
                returns.Add(return_rate);
            }

            // 使用GARCH模型预测波动率
            try
            {
                // 计算当前方差（最后一个收益率的平方作为近似）
                double currentVariance = Math.Pow(returns.Last(), 2);
                return Math.Sqrt(garchModel.PredictVolatility(currentVariance, new int[] { 1 })[0] * 250); // 年化
            }
            catch
            {
                // 如果GARCH预测失败，回退到EWMA方法
                return CalculateEWMAVolatility();
            }
        }

        #endregion

        #region 动态止损算法

        /// <summary>
        /// 计算动态止损位
        /// </summary>
        /// <param name="entryPrice">入场价格</param>
        /// <param name="currentPrice">当前价格</param>
        /// <param name="isLong">是否多头仓位</param>
        /// <param name="riskMetrics">风险度量模块</param>
        /// <returns>动态止损价格</returns>
        public double CalculateDynamicStopLoss(double entryPrice, double currentPrice, bool isLong, 
            RiskMetrics riskMetrics = null)
        {
            if (entryPrice <= 0 || currentPrice <= 0)
            {
                throw new ArgumentException("价格必须大于0");
            }

            // 获取当前ATR
            double currentATR = GetCurrentATR();
            if (currentATR == 0)
            {
                currentATR = Math.Abs(currentPrice - entryPrice) * 0.02; // 默认2%作为ATR估计
            }

            // 判断波动率环境
            VolatilityEnvironment volEnv = ClassifyVolatilityEnvironment();

            // 根据波动率环境选择倍数
            double atrMultiplier = volEnv switch
            {
                VolatilityEnvironment.Low => LOW_VOLATILITY_MULTIPLIER,
                VolatilityEnvironment.Medium => MEDIUM_VOLATILITY_MULTIPLIER,
                VolatilityEnvironment.High => HIGH_VOLATILITY_MULTIPLIER,
                VolatilityEnvironment.Extreme => HIGH_VOLATILITY_MULTIPLIER * 1.2,
                _ => MEDIUM_VOLATILITY_MULTIPLIER
            };

            // 趋势调整
            if (_trendDirection == TrendDirection.Uptrend && isLong)
            {
                atrMultiplier *= (1 - _trendStrength * 0.2); // 趋势向上时减少止损距离
            }
            else if (_trendDirection == TrendDirection.Downtrend && !isLong)
            {
                atrMultiplier *= (1 - _trendStrength * 0.2); // 趋势向下时减少止损距离
            }
            else if (_trendDirection == TrendDirection.Sideways)
            {
                atrMultiplier *= 1.3; // 震荡市场增加止损距离
            }

            // 计算止损距离
            double stopDistance = currentATR * atrMultiplier;

            // VaR调整（如果提供了风险度量模块）
            if (riskMetrics != null)
            {
                try
                {
                    double var95 = riskMetrics.CalculateHistoricalVaR(0.95, Math.Abs(currentPrice - entryPrice));
                    double varAdjustment = var95 / Math.Abs(currentPrice - entryPrice);
                    stopDistance = Math.Max(stopDistance, currentPrice * varAdjustment);
                }
                catch
                {
                    // VaR计算失败时使用ATR方法
                }
            }

            // 限制止损距离在合理范围内
            double minStopDistance = currentPrice * MIN_STOP_DISTANCE_RATIO;
            double maxStopDistance = currentPrice * MAX_STOP_DISTANCE_RATIO;
            stopDistance = Math.Max(minStopDistance, Math.Min(maxStopDistance, stopDistance));

            // 计算最终止损价格
            if (isLong)
            {
                return currentPrice - stopDistance;
            }
            else
            {
                return currentPrice + stopDistance;
            }
        }

        /// <summary>
        /// 计算跟踪止损位
        /// </summary>
        /// <param name="entryPrice">入场价格</param>
        /// <param name="currentPrice">当前价格</param>
        /// <param name="highestPrice">最高价（多头）或最低价（空头）</param>
        /// <param name="isLong">是否多头仓位</param>
        /// <returns>跟踪止损价格</returns>
        public double CalculateTrailingStopLoss(double entryPrice, double currentPrice, 
            double highestPrice, bool isLong)
        {
            if (entryPrice <= 0 || currentPrice <= 0 || highestPrice <= 0)
            {
                throw new ArgumentException("价格必须大于0");
            }

            double currentATR = GetCurrentATR();
            if (currentATR == 0)
            {
                currentATR = Math.Abs(currentPrice - entryPrice) * 0.02;
            }

            // 判断波动率环境并调整ATR倍数
            VolatilityEnvironment volEnv = ClassifyVolatilityEnvironment();
            double atrMultiplier = volEnv switch
            {
                VolatilityEnvironment.Low => LOW_VOLATILITY_MULTIPLIER,
                VolatilityEnvironment.Medium => MEDIUM_VOLATILITY_MULTIPLIER,
                VolatilityEnvironment.High => HIGH_VOLATILITY_MULTIPLIER,
                _ => MEDIUM_VOLATILITY_MULTIPLIER
            };

            // 计算盈利情况
            double currentProfit = isLong ? 
                (currentPrice - entryPrice) / entryPrice : 
                (entryPrice - currentPrice) / entryPrice;

            // 更新最高/最低盈利
            if (isLong)
            {
                _highestProfit = Math.Max(_highestProfit, currentProfit);
            }
            else
            {
                _lowestProfit = Math.Min(_lowestProfit, currentProfit);
            }

            // 计算跟踪止损距离
            double trailingDistance = currentATR * atrMultiplier;

            // 根据盈利情况调整跟踪距离
            if (currentProfit > 0.05) // 盈利超过5%时收紧止损
            {
                trailingDistance *= 0.7;
            }
            else if (currentProfit > 0.02) // 盈利超过2%时稍微收紧
            {
                trailingDistance *= 0.85;
            }

            // 计算跟踪止损价格
            double trailingStopPrice;
            if (isLong)
            {
                trailingStopPrice = highestPrice - trailingDistance;
                
                // 确保跟踪止损只能上移，不能下移
                if (_currentStopLevel > 0)
                {
                    trailingStopPrice = Math.Max(trailingStopPrice, _currentStopLevel);
                }
            }
            else
            {
                trailingStopPrice = highestPrice + trailingDistance;
                
                // 确保跟踪止损只能下移，不能上移
                if (_currentStopLevel > 0)
                {
                    trailingStopPrice = Math.Min(trailingStopPrice, _currentStopLevel);
                }
            }

            // 更新当前止损水平
            _currentStopLevel = trailingStopPrice;

            return trailingStopPrice;
        }

        #endregion

        #region 趋势识别方法

        /// <summary>
        /// 分析当前趋势
        /// </summary>
        /// <returns>趋势分析结果</returns>
        public (TrendDirection Direction, double Strength) AnalyzeTrend()
        {
            if (_historicalData.Count < TREND_LOOKBACK_PERIOD)
            {
                return (TrendDirection.Unknown, 0.0);
            }

            var recentPrices = _historicalData.Skip(_historicalData.Count - TREND_LOOKBACK_PERIOD)
                                              .Select(p => p.Close).ToList();

            // 计算线性趋势
            double slope = CalculateLinearTrendSlope(recentPrices);
            double r_squared = CalculateTrendRSquared(recentPrices);

            _trendStrength = r_squared; // R²作为趋势强度指标

            // 判断趋势方向
            if (r_squared < TREND_THRESHOLD)
            {
                _trendDirection = TrendDirection.Sideways;
            }
            else if (slope > 0)
            {
                _trendDirection = TrendDirection.Uptrend;
            }
            else
            {
                _trendDirection = TrendDirection.Downtrend;
            }

            return (_trendDirection, _trendStrength);
        }

        /// <summary>
        /// 计算价格序列的线性趋势斜率
        /// </summary>
        /// <param name="prices">价格序列</param>
        /// <returns>趋势斜率</returns>
        private double CalculateLinearTrendSlope(List<double> prices)
        {
            if (prices.Count < 2)
                return 0.0;

            int n = prices.Count;
            double sumX = n * (n - 1) / 2.0;
            double sumY = prices.Sum();
            double sumXY = prices.Select((price, index) => index * price).Sum();
            double sumXSquared = Enumerable.Range(0, n).Sum(i => i * i);

            double slope = (n * sumXY - sumX * sumY) / (n * sumXSquared - sumX * sumX);
            
            return slope;
        }

        /// <summary>
        /// 计算趋势的R平方值
        /// </summary>
        /// <param name="prices">价格序列</param>
        /// <returns>R平方值</returns>
        private double CalculateTrendRSquared(List<double> prices)
        {
            if (prices.Count < 2)
                return 0.0;

            double slope = CalculateLinearTrendSlope(prices);
            double meanY = prices.Average();
            
            double sumSquaredTotal = prices.Sum(p => Math.Pow(p - meanY, 2));
            
            double sumSquaredResiduals = 0.0;
            for (int i = 0; i < prices.Count; i++)
            {
                double predictedY = slope * i + (meanY - slope * (prices.Count - 1) / 2.0);
                sumSquaredResiduals += Math.Pow(prices[i] - predictedY, 2);
            }

            if (sumSquaredTotal == 0)
                return 0.0;

            return 1 - (sumSquaredResiduals / sumSquaredTotal);
        }

        #endregion

        #region 波动率环境分类

        /// <summary>
        /// 分类当前波动率环境
        /// </summary>
        /// <returns>波动率环境类型</returns>
        public VolatilityEnvironment ClassifyVolatilityEnvironment()
        {
            if (_volatilityEstimates.Count == 0)
            {
                return VolatilityEnvironment.Medium;
            }

            double currentVol = _volatilityEstimates.LastOrDefault();
            
            // 计算历史波动率的分位数
            if (_volatilityEstimates.Count >= 20)
            {
                var sortedVols = _volatilityEstimates.OrderBy(v => v).ToList();
                double vol25 = sortedVols[(int)(sortedVols.Count * 0.25)];
                double vol75 = sortedVols[(int)(sortedVols.Count * 0.75)];
                double vol90 = sortedVols[(int)(sortedVols.Count * 0.90)];

                if (currentVol < vol25)
                    return VolatilityEnvironment.Low;
                else if (currentVol > vol90)
                    return VolatilityEnvironment.Extreme;
                else if (currentVol > vol75)
                    return VolatilityEnvironment.High;
                else
                    return VolatilityEnvironment.Medium;
            }

            // 如果历史数据不足，使用简单阈值判断
            if (currentVol < 0.10)
                return VolatilityEnvironment.Low;
            else if (currentVol > 0.30)
                return VolatilityEnvironment.High;
            else
                return VolatilityEnvironment.Medium;
        }

        #endregion

        #region 辅助方法

        /// <summary>
        /// 更新ATR值
        /// </summary>
        private void UpdateATR()
        {
            double newATR = CalculateFullATR();
            if (newATR > 0)
            {
                _atrValues.Add(newATR);

                // 限制ATR历史记录长度
                if (_atrValues.Count > 100)
                {
                    _atrValues.RemoveRange(0, _atrValues.Count - 100);
                }
            }
        }

        /// <summary>
        /// 更新波动率估计
        /// </summary>
        private void UpdateVolatilityEstimates()
        {
            double histVol = CalculateHistoricalVolatility();
            double ewmaVol = CalculateEWMAVolatility();

            // 使用加权平均作为综合波动率估计
            double combinedVol = 0.6 * histVol + 0.4 * ewmaVol;
            
            if (combinedVol > 0)
            {
                _volatilityEstimates.Add(combinedVol);

                // 限制波动率历史记录长度
                if (_volatilityEstimates.Count > 100)
                {
                    _volatilityEstimates.RemoveRange(0, _volatilityEstimates.Count - 100);
                }
            }
        }

        /// <summary>
        /// 更新趋势分析
        /// </summary>
        private void UpdateTrendAnalysis()
        {
            if (_historicalData.Count >= TREND_LOOKBACK_PERIOD)
            {
                AnalyzeTrend();
            }
        }

        /// <summary>
        /// 计算指数移动平均
        /// </summary>
        /// <param name="values">数值序列</param>
        /// <param name="period">周期</param>
        /// <returns>EMA值</returns>
        private double CalculateEMA(IEnumerable<double> values, int period)
        {
            var valueList = values.ToList();
            if (valueList.Count == 0)
                return 0.0;

            double alpha = 2.0 / (period + 1);
            double ema = valueList[0];

            for (int i = 1; i < valueList.Count; i++)
            {
                ema = alpha * valueList[i] + (1 - alpha) * ema;
            }

            return ema;
        }

        #endregion

        #region 状态查询方法

        /// <summary>
        /// 获取当前状态信息
        /// </summary>
        /// <returns>状态信息</returns>
        public (double ATR, double Volatility, TrendDirection Trend, double TrendStrength, 
                VolatilityEnvironment VolEnv) GetCurrentState()
        {
            return (GetCurrentATR(), 
                    _volatilityEstimates.LastOrDefault(),
                    _trendDirection, 
                    _trendStrength,
                    ClassifyVolatilityEnvironment());
        }

        /// <summary>
        /// 获取数据统计信息
        /// </summary>
        /// <returns>数据统计</returns>
        public (int DataCount, int ATRCount, DateTime LastUpdate) GetDataStats()
        {
            return (_historicalData.Count, _atrValues.Count, _lastUpdateTime);
        }

        /// <summary>
        /// 重置止损追踪状态
        /// </summary>
        public void ResetTrailingStopState()
        {
            _highestProfit = 0.0;
            _lowestProfit = 0.0;
            _currentStopLevel = 0.0;
        }

        #endregion
    }
}
